import random


def 生成齐夫分布(包数, 流数, 参数=1.0):
    tmp = 0.0
    for k in range(1, 流数 + 1):
        tmp += 1.0/(k**参数)
    C = 包数/tmp
    流长度 = []
    for k in range(1, 流数 + 1):
        流长度.append(C/(k**参数))
    return 流长度


def 生成五元组():
    '''随机生成一个五元组(源IP地址, 目的IP地址, 协议类型, 源端口号, 目的端口号)'''
    srcip = random.randint(1, 0xffffffff)
    dstip = random.randint(1, 0xffffffff)
    proto = random.randint(1, 2)
    if 1 == proto:
        proto = 6
    elif 2 == proto:
        proto = 17
    srcport = random.randint(1, 65535)
    dstport = random.randint(1, 65535)
    五元组 = {"源地址": srcip, "目标地址": dstip, "协议类型": proto,
           "源端口号": srcport, "目标端口号": dstport}
    return 五元组


def 生成流标识符():
    五元组 = 生成五元组()
    流标识符 = "%08x\t%08x\t%02x\t%04x\t%04x" % \
        (五元组["源地址"], 五元组["目标地址"], 五元组["协议类型"], 五元组["源端口号"], 五元组["目标端口号"])
    return 流标识符


def 检查流标识符的格式(流标识符):
    # 检查流标识符是否符合这样的格式:"109.26.99.201\t199.137.227.17\t6\t62692\t4231" 
    if not isinstance(流标识符, str):
        return False
    if 4 == 流标识符.count("\t") and 流标识符.count(".") in [0, 6]:
        return True
    else:
        return False


def 字节流转整数(字节流):
    assert(isinstance(字节流, bytearray))
    结果 = 0
    for 子项 in 字节流:
        结果 = 结果*256 + 子项
    return 结果


def 标识符转字节流(流标识符):
    # 这里的流标识符必须是"源地址\t目标地址\t协议类型\t源端口号\t目标端口号"的形式
    if not 检查流标识符的格式(流标识符):
        raise SystemExit("这是一个非法的流标识符:", 流标识符)
    流标识符 = 流标识符.strip()
    子项 = 流标识符.split("\t")
    结果 = bytearray.fromhex(子项[0])
    for 索引 in range(1, 5):
        结果 += bytearray.fromhex(子项[索引])
    return 结果


def 字节流转标识符(字节流):
    assert(isinstance(字节流, bytearray) and 13 == len(字节流))
    源地址 = 字节流转整数(字节流[0:4])
    目标地址 = 字节流转整数(字节流[4:8])
    协议类型 = 字节流[8]
    源端口号 = 字节流转整数(字节流[9:11])
    目标端口号 = 字节流转整数(字节流[11:13])
    标识符 = "%08x\t%08x\t%02x\t%04x\t%04x" % (源地址,目标地址, 协议类型, 源端口号, 目标端口号)
    return 标识符


def 字节流异或(字节流1, 字节流2):
    assert(isinstance(字节流1, bytearray) and isinstance(字节流2, bytearray))
    assert(len(字节流1) == len(字节流2))
    临变 = len(字节流1)
    结果 = bytearray(临变)
    for 索引 in range(临变):
        结果[索引] = 字节流1[索引] ^ 字节流2[索引]
    return 结果


def IP地址转整数(地址):
    子项集 = 地址.split(".")
    返回值 = 0
    for 子项 in 子项集:
        返回值 = (返回值 << 8) + int(子项)
    return 返回值


def 计算误差(目标数列, 生成数列):
    误差 = 0.0
    for a, b in zip(目标数列, 生成数列):
        误差 += (a - b)**2
    return 误差


def 齐夫拟合(数列):
    # 将数列拟合成为一个齐夫分布并返回齐夫分布的skewness parameter
    数列.sort(reverse=True)
    流数 = len(数列)
    包数 = sum(数列)
    最小误差 = -1
    拟合参数 = -1
    for 参数 in range(50, 150):
        参数 = 参数/100.0
        拟合数列 = 生成齐夫分布(包数, 流数, 参数)
        误差 = 计算误差(数列, 拟合数列)
        if -1 == 最小误差 or 误差 < 最小误差:
            最小误差 = 误差
            拟合参数 = 参数
    return 拟合参数
